/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace DaveSexton.DocProject.DocSites
{
	public abstract class QueryExpression
	{
		#region Public Properties
		public abstract bool IsOptimized { get; }

		public QueryExpression Parent
		{
			get
			{
				return parent;
			}
			internal set
			{
				parent = value;
			}
		}
		#endregion

		#region Private / Protected
		private QueryExpression parent;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="QueryExpression" /> class for derived classes.
		/// </summary>
		protected QueryExpression(QueryExpression parent)
		{
			this.parent = parent;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="QueryExpression" /> class for derived classes.
		/// </summary>
		protected QueryExpression()
		{
		}
		#endregion

		#region Methods
		/// <summary>
		/// Collapses the expression and its subexpressions into smaller ones, if possible.
		/// </summary>
		/// <remarks>
		/// If a derived-type cannot be normalized any further then it should return a clone of itself.
		/// <para>Implementations must not return null.  At the least, return <see cref="EmptyQueryExpression.Value"/>.</para>
		/// </remarks>
		public abstract QueryExpression Normalize();

		/// <summary>
		/// Improves the expression and its subexpressions for maximum evaluation speed and efficiency.
		/// </summary>
		/// <remarks>
		/// If a derived-type cannot be optimized any further then it should return a clone of itself.
		/// <para>Implementations must not return null.  At the least, return <see cref="EmptyQueryExpression.Value"/>.</para>
		/// </remarks>
		public abstract QueryExpression Optimize();

		public abstract void Evaluate(Action<QueryExpression> action);

		public abstract void AppendToString(StringBuilder output);

		public sealed override string ToString()
		{
			StringBuilder expr = new StringBuilder(64);

			AppendToString(expr);

			return expr.ToString();
		}
		#endregion
	}
}
